#include "ALU_CLUSTER.h"

ALU_CLUSTER::ALU_CLUSTER()
{
	for(int i = 0; i < ALU_CLUSTER_ADD_SIZE; i++)
	{
		aluc_add[i] = new ALU_ADD();
		aluc_add_lrf[i] = new LRF();
		aluc_add[i]->fu_lrf = aluc_add_lrf[i];
	}
	for(int i = 0; i < ALU_CLUSTER_MUL_SIZE; i++)
	{
		aluc_mul[i] = new ALU_MUL();
		aluc_mul_lrf[i] = new LRF();
		aluc_mul[i]->fu_lrf = aluc_mul_lrf[i];
	}
	for(int i = 0; i < ALU_CLUSTER_DSQ_SIZE; i++)
	{
		aluc_dsq[i] = new ALU_DSQ();
		aluc_dsq_lrf[i] = new LRF();
		aluc_dsq[i]->fu_lrf = aluc_dsq_lrf[i];
	}
	
}

int ALU_CLUSTER::set_fu(int fu, int fu_num, int inputA, float inputFA, int inputB, float inputFB, int opCode, int regDst)
{
	int rv = 0;

	if ((fu == ALU_ADD_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_ADD_SIZE)))
	{
		aluc_add[fu_num]->inputA = inputA;
		aluc_add[fu_num]->inputB = inputB;
		aluc_add[fu_num]->inputFA = inputFA;
		aluc_add[fu_num]->inputFB = inputFB;
		aluc_add[fu_num]->OpCode = opCode;
		aluc_add[fu_num]->regDst = regDst;
		rv = 1;
	}
	else if ((fu == ALU_MUL_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_MUL_SIZE)))
	{
		aluc_mul[fu_num]->inputA = inputA;
		aluc_mul[fu_num]->inputB = inputB;
		aluc_mul[fu_num]->inputFA = inputFA;
		aluc_mul[fu_num]->inputFB = inputFB;
		aluc_mul[fu_num]->OpCode = opCode;
		aluc_mul[fu_num]->regDst = regDst;
		rv = 1;
	}
	else if ((fu == ALU_DSQ_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_DSQ_SIZE)))
	{
		aluc_dsq[fu_num]->inputA = inputA;
		aluc_dsq[fu_num]->inputB = inputB;
		aluc_dsq[fu_num]->inputFA = inputFA;
		aluc_dsq[fu_num]->inputFB = inputFB;
		aluc_dsq[fu_num]->OpCode = opCode;
		aluc_dsq[fu_num]->regDst = regDst;
		rv = 1;
	}
	
	return rv;
}

int ALU_CLUSTER::get_fu(int fu, int fu_num, int& inputA, float& inputFA, int& inputB, float& inputFB, int& opCode)
{
	int rv = 0;

	if ((fu == ALU_ADD_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_ADD_SIZE)))
	{
		inputA = aluc_add[fu_num]->inputA;
		inputB = aluc_add[fu_num]->inputB;
		inputFA = aluc_add[fu_num]->inputFA;
		inputFB = aluc_add[fu_num]->inputFB;
		opCode = aluc_add[fu_num]->OpCode;
		rv = 1;
	}
	else if ((fu == ALU_MUL_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_MUL_SIZE)))
	{
		inputA = aluc_mul[fu_num]->inputA;
		inputB = aluc_mul[fu_num]->inputB;
		inputFA = aluc_mul[fu_num]->inputFA;
		inputFB = aluc_mul[fu_num]->inputFB;
		opCode = aluc_mul[fu_num]->OpCode;
		rv = 1;
	}
	else if ((fu == ALU_DSQ_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_DSQ_SIZE)))
	{
		inputA = aluc_dsq[fu_num]->inputA;
		inputB = aluc_dsq[fu_num]->inputB;
		inputFA = aluc_dsq[fu_num]->inputFA;
		inputFB = aluc_dsq[fu_num]->inputFB;
		opCode = aluc_dsq[fu_num]->OpCode;
		rv = 1;
	}
	
	return rv;
}

int ALU_CLUSTER::update(int fu, int fu_num)
{
	int rv = 0;

	if ((fu == ALU_ADD_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_ADD_SIZE)))
	{
		aluc_add[fu_num]->update();
		rv = 1;
	}
	else if ((fu == ALU_MUL_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_MUL_SIZE)))
	{
		aluc_mul[fu_num]->update();
		rv = 1;
	}
	else if ((fu == ALU_DSQ_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_DSQ_SIZE)))
	{
		aluc_dsq[fu_num]->update();
		rv = 1;
	}
	
	return rv;
}

int ALU_CLUSTER::getOutput(int fu, int fu_num)
{
	if ((fu == ALU_ADD_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_ADD_SIZE)))
	{
		return aluc_add[fu_num]->getOutput();
	}
	else if ((fu == ALU_MUL_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_MUL_SIZE)))
	{
		return aluc_mul[fu_num]->getOutput();
	}
	else if ((fu == ALU_DSQ_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_DSQ_SIZE)))
	{
		return aluc_dsq[fu_num]->getOutput();
	}
	
	return -1;
}

float ALU_CLUSTER::getOutputF(int fu, int fu_num)
{
	if ((fu == ALU_ADD_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_ADD_SIZE)))
	{
		return aluc_add[fu_num]->getOutputF();
	}
	else if ((fu == ALU_MUL_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_MUL_SIZE)))
	{
		return aluc_mul[fu_num]->getOutputF();
	}
	else if ((fu == ALU_DSQ_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_DSQ_SIZE)))
	{
		return aluc_dsq[fu_num]->getOutputF();
	}
	
	return -1;
}

int ALU_CLUSTER::isReady(int fu, int fu_num)
{
	if ((fu == ALU_ADD_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_ADD_SIZE)))
	{
		return aluc_add[fu_num]->isReady();
	}
	else if ((fu == ALU_MUL_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_MUL_SIZE)))
	{
		return aluc_mul[fu_num]->isReady();
	}
	else if ((fu == ALU_DSQ_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_DSQ_SIZE)))
	{
		return aluc_dsq[fu_num]->isReady();
	}
	
	return -1;
}

int ALU_CLUSTER::isFinished(int fu, int fu_num)
{
	if ((fu == ALU_ADD_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_ADD_SIZE)))
	{
		return aluc_add[fu_num]->isFinished();
	}
	else if ((fu == ALU_MUL_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_MUL_SIZE)))
	{
		return aluc_mul[fu_num]->isFinished();
	}
	else if ((fu == ALU_DSQ_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_DSQ_SIZE)))
	{
		return aluc_dsq[fu_num]->isReady();
	}
	
	return -1;
}

int ALU_CLUSTER::set_lrf(int fu, int fu_num, int lrf_entry, unsigned char value)
{
	int rv = 0;

	if ((fu == ALU_ADD_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_ADD_SIZE)))
	{
		rv = aluc_add_lrf[fu_num]->write(lrf_entry, value);
	}
	else if ((fu == ALU_MUL_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_MUL_SIZE)))
	{
		rv = aluc_mul_lrf[fu_num]->write(lrf_entry, value);
	}
	else if ((fu == ALU_DSQ_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_DSQ_SIZE)))
	{
		rv = aluc_dsq_lrf[fu_num]->write(lrf_entry, value);
	}
	
	return rv;
}

int ALU_CLUSTER::set_lrf(int fu, int fu_num, int lrf_entry, int value)
{
	int rv = 0;

	if ((fu == ALU_ADD_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_ADD_SIZE)))
	{
		rv = aluc_add_lrf[fu_num]->write(lrf_entry, value);
	}
	else if ((fu == ALU_MUL_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_MUL_SIZE)))
	{
		rv = aluc_mul_lrf[fu_num]->write(lrf_entry, value);
	}
	else if ((fu == ALU_DSQ_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_DSQ_SIZE)))
	{
		rv = aluc_dsq_lrf[fu_num]->write(lrf_entry, value);
	}
	
	return rv;
}

int ALU_CLUSTER::set_lrf(int fu, int fu_num, int lrf_entry, float value)
{
	int rv = 0;

	if ((fu == ALU_ADD_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_ADD_SIZE)))
	{
		rv = aluc_add_lrf[fu_num]->write(lrf_entry, value);
	}
	else if ((fu == ALU_MUL_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_MUL_SIZE)))
	{
		rv = aluc_mul_lrf[fu_num]->write(lrf_entry, value);
	}
	else if ((fu == ALU_DSQ_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_DSQ_SIZE)))
	{
		rv = aluc_dsq_lrf[fu_num]->write(lrf_entry, value);
	}
	
	return rv;
}

int ALU_CLUSTER::set_lrf(int fu, int fu_num, LRF* lrf)
{
	int rv = 0;

	if ((fu == ALU_ADD_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_ADD_SIZE)))
	{
		aluc_add_lrf[fu_num] = lrf;
		rv = 1;
	}
	else if ((fu == ALU_MUL_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_MUL_SIZE)))
	{
		aluc_mul_lrf[fu_num] = lrf;
		rv = 1;
	}
	else if ((fu == ALU_DSQ_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_DSQ_SIZE)))
	{
		aluc_dsq_lrf[fu_num] = lrf;
		rv = 1;
	}
	
	return rv;
}

int ALU_CLUSTER::get_lrf(int fu, int fu_num, int lrf_entry, unsigned char& value)
{
	int rv = 0;

	if ((fu == ALU_ADD_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_ADD_SIZE)))
	{
		rv = aluc_add_lrf[fu_num]->read(lrf_entry, value);
	}
	else if ((fu == ALU_MUL_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_MUL_SIZE)))
	{
		rv = aluc_mul_lrf[fu_num]->read(lrf_entry, value);
	}
	else if ((fu == ALU_DSQ_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_DSQ_SIZE)))
	{
		rv = aluc_dsq_lrf[fu_num]->read(lrf_entry, value);
	}
	
	return rv;
}

int ALU_CLUSTER::get_lrf(int fu, int fu_num, int lrf_entry, int& value)
{
	int rv = 0;

	if ((fu == ALU_ADD_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_ADD_SIZE)))
	{
		rv = aluc_add_lrf[fu_num]->read(lrf_entry, value);
	}
	else if ((fu == ALU_MUL_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_MUL_SIZE)))
	{
		rv = aluc_mul_lrf[fu_num]->read(lrf_entry, value);
	}
	else if ((fu == ALU_DSQ_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_DSQ_SIZE)))
	{
		rv = aluc_dsq_lrf[fu_num]->read(lrf_entry, value);
	}
	
	return rv;
}

int ALU_CLUSTER::get_lrf(int fu, int fu_num, int lrf_entry, float& value)
{
	int rv = 0;

	if ((fu == ALU_ADD_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_ADD_SIZE)))
	{
		rv = aluc_add_lrf[fu_num]->read(lrf_entry, value);
	}
	else if ((fu == ALU_MUL_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_MUL_SIZE)))
	{
		rv = aluc_mul_lrf[fu_num]->read(lrf_entry, value);
	}
	else if ((fu == ALU_DSQ_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_DSQ_SIZE)))
	{
		rv = aluc_dsq_lrf[fu_num]->read(lrf_entry, value);
	}
	
	return rv;
}

LRF* ALU_CLUSTER::get_lrf(int fu, int fu_num)
{
	LRF* rv = 0;

	if ((fu == ALU_ADD_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_ADD_SIZE)))
	{
		rv = aluc_add_lrf[fu_num];
	}
	else if ((fu == ALU_MUL_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_MUL_SIZE)))
	{
		rv = aluc_mul_lrf[fu_num];
	}
	else if ((fu == ALU_DSQ_FU) && ((fu_num >= 0) && (fu_num < ALU_CLUSTER_DSQ_SIZE)))
	{
		rv = aluc_dsq_lrf[fu_num];
	}
	
	return rv;
}
